// 基于阻塞队列的生产消费模型

#include "BlockQueue.hpp"
#include "Task.hpp"
#include <pthread.h>
#include <ctime>
#include <cmath>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

const string opers = "+-*/%)(&"; // 用于随机生成op

void *consumer(void *arg)
{
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(arg);

    while(true)
    {
        sleep(1);  //这里延时1s，即程序会一开始生产数据到阻塞队列，满了之后生产者就开始等待消费者消费，后续就是消费一个生产一个的规律下去，使得两个线程的执行有一定的顺序
        Task t;
        bq->pop(&t); //从阻塞队列中获取数据
        t(); //执行获取到的任务
        cout << "consumer data: " << t.PrintResult() << endl;
    }
    return nullptr;
}

void *productor(void *arg)
{
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(arg);

    while (true)
    {
        int x = rand() % 20;
        int y = rand() % 20;
        char op = opers[rand() % (opers.size())];

        Task t = Task(x, y, op); // 随机获取任务
        cout << "productor task: " << t.PrintTask() << endl;
        bq->push(t); //将任务生产进阻塞队列
    }

    return nullptr;
}

int main()
{
    srand((unsigned int)time(nullptr) ^ getpid() ^ pthread_self()); // 只是为了形成更随机的数据
    pthread_t c, p;
    BlockQueue<Task> *bq = new BlockQueue<Task>();
    pthread_create(&c, nullptr, consumer, bq);
    pthread_create(&p, nullptr, productor, bq);

    pthread_join(c, nullptr);
    pthread_join(p, nullptr);
    return 0;
}